import { Prop, Emit, Watch, ComponentBase } from 'vue-facing-decorator'
import Render from '@/render/Render'
import toNative from '@/utils/toNative'
import { wait } from '@/utils/util'
import { type ComponentPublicInstance } from 'vue'
import { message, Upload, UploadDragger, type UploadFile } from 'ant-design-vue'
import type { UploadChangeParam } from 'ant-design-vue/es/upload/interface'
import {
    UploadOutlined
} from '@ant-design/icons-vue'


export interface UploadFileDto extends UploadFile {
    fullBase64?: string
    base64?: string
    isCover?: boolean | string
    isChoose?: boolean
}

export interface ParamsDto {
    autoUpload: boolean
    accept: string
    limit: number
    maxSize: number
    listType: 'text' | 'picture' | 'picture-card'
    text: string
    hint: string
    hideListType: boolean
    exit: number
}

@ComponentBase
export class FileUploadDragger extends Render {
    fileList = [] as UploadFileDto[]

    @Prop() params?: ParamsDto
    @Prop() modelValue!: string | string[]
    @Prop({default: false}) multiple?: boolean

    visible = false
    previewSrc = ''

    @Emit('update:modelValue')
    handleEmit() {
        return this.fileList
    }

    @Emit('change')
    handleChange(fileList: UploadFileDto[]) {
        return fileList
    }

    @Watch('modelValue', { immediate: true, deep: true })
    handleWatchModelValue(val: string | string[] | UploadFileDto[]) {
        if (!val?.length) {
            this.fileList = []
            return
        }
        const valueList = Array.isArray(val) ? val : [val]
        valueList.forEach((item, index) => {
            if (!(item as UploadFileDto).uid) {
                const nameStart = (item as string).lastIndexOf('/')
                this.fileList = []
                this.fileList.push({
                    uid: index.toString(),
                    name: (item as string).substring(nameStart + 1),
                    url: item,
                    thumbUrl: item
                } as UploadFileDto)
                this.handleEmit()
            }
        })
    }

    async onChange(info: UploadChangeParam<UploadFileDto>) {
        info.fileList.forEach(async (item) => {
            item.fullBase64 = (await this.getBase64(item.originFileObj as File)) as string
            item.base64 = item.fullBase64?.split(';base64,')?.[1] ?? ''
        })
        this.handleEmit()
        await wait(300)
        this.handleChange(info.fileList)
    }

    onRemove() {
        this.handleEmit()
    }

    getBase64(raw: File) {
        return new Promise((resolve) => {
            const imgFile = new FileReader()
            imgFile.readAsDataURL(raw)
            imgFile.onload = (res) => {
                const base64 = res?.target?.result as string
                resolve(base64)
            }
        })
    }

    beforeUpload(file: UploadFileDto) {
        // 限制上传数量
        if (this.fileList.length > (this.params?.limit || 1)) {
            message.error('最多上传' + (this.params?.limit || 1) + '张图片')
            return false
        }

        if (this.params?.hideListType && this.params?.limit && this.params?.exit && this.params.exit > this.params.limit ) {
            message.error('最多上传' + (this.params?.limit || 1) + '张图片')
            return false
        }

        // 限制上传大小
        const maxSize = this.params?.maxSize || 5
        if ((file.size as number) > maxSize * 1024 * 1024) {
            message.error(`上传图片大小不能超过${maxSize}M`)
            return Upload.LIST_IGNORE
        }
        return this.params?.autoUpload ?? false
    }

    onPreview(url: string) {
        this.visible = true
        this.previewSrc = url
    }

    onMounted() {
        console.log('reload')
    }

    render(data: ComponentPublicInstance) {
        return (
            <div>
                <UploadDragger
                    v-model:file-list={this.fileList}
                    action="#"
                    beforeUpload={this.beforeUpload}
                    accept={this.params?.accept}
                    listType={this.params?.listType || 'text'}
                    maxCount={this.params?.limit || 1}
                    multiple={this.multiple || false}
                    onChange={this.onChange}
                    onRemove={this.onRemove}
                    v-slots={{
                        default: () => {
                            return (
                                data?.$slots?.default?.() ?? (
                                    <div class="flex flex-col items-center justify-center">
                                        <UploadOutlined style={'color: #3E5FF5'} />
                                        <span class="mt-10px">点击上传或将文件拖动到此区域</span>
                                    </div>
                                )
                            )
                        }
                    }}
                ></UploadDragger>
            </div>
        )
    }
}

export default toNative<
    { params?: Partial<ParamsDto>, multiple?: boolean},
    {
        change: (fileList: UploadFileDto[]) => void
            }
            >(FileUploadDragger)
